package tss.clientGui;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JTextField;
import javax.swing.Timer;

import tss.client.ClientInterface;
import tss.common.ExtensionStates;
import tss.common.LineStates;

public class ClientProcessor {

	private ClientInterface service = null;
	private ClientUI ui = null;
	private int extension = -1;
	private LineStates lineState = LineStates.Busy;
	private SoundRunner sound = null;
	private boolean dialing = false;
	
	public ClientProcessor(ClientInterface service) {
		this.service = service;
		this.ui = new ClientUI(this);
	}

	public void onWindowClosing() {
		if (sound != null)
			sound.interrupt();
		
		if (validExtension(extension))
			service.disconnectServer(extension);
			
		System.exit(0);
	}

	public boolean onConnectClick(String host, int port) {
		try {
			if (host.length() == 0 || port == 0) {
				ui.writeMessage("Must specify host and port to connect to Phone System.");
			} else {
				ui.writeMessage("Connecting to Phone System.");
				extension = service.connectServer(host, port);
				if(validExtension(extension)) {
					onConnected();
					return true;
				} 
			}
		} catch (Exception ex) {
			ui.writeMessage("Server Error: " + ex.getMessage());
		}
		return false;
	}
	
	private void onConnected() {
		ui.setCurrentPhone(extension);
		ui.writeMessage("Connected on Line: " + extension);

		startUpdateTimer();
	}
	
	final int delay = 100;
	public void startUpdateTimer() {
		ActionListener taskPerformer = new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				updateExtensionStates();
				updateLineState();
			}
		};
		new Timer(delay, taskPerformer).start();
	}

	public void updateExtensionStates() {
		ExtensionStates[] states = service.getExtensionStates();
		for(int i = 1; i <= 16; i++)
			if (i != extension)
				ui.setPhoneState(i, states[i - 1]);
	}
	
	public void updateLineState() {
		ui.setPhoneLineState(extension, service.getLineState());
		switch(service.getLineState()) {
		case Open:
			dialing = false;
			clearSound();
			ui.setActionState(false, "No Action");
			break;
		case Busy:
			setSound(SoundTypes.Busy);
			ui.setActionState(true, "Hang Up");
			break;
		case Connecting:
			ui.setActionState(false, "No Action");
			break;
		case Dialing:
			if (dialing){
				setSound(SoundTypes.Dial);
				ui.setActionState(true, "Hang Up");
			}
			break;
		case Ringing:
			if (dialing)
				ui.setActionState(true, "Hang Up");
			else
				ui.setActionState(true, "Pick Up");
			setSound(SoundTypes.Ring);
			break;
		case Talking:
			ui.setActionState(true, "Hang Up");
			clearSound();
			break;
		case Terminating:
			ui.setActionState(false, "No Action");
			clearSound();
			break;
		case Error:
			if (dialing) {
				ui.setActionState(true, "Hang Up");
				setSound(SoundTypes.Unavailable);
			} else {
				clearSound();	
			}
		}		
		

	}
	
	public void onPhoneExtensionClick(int extension) {
		if (validExtension(extension) && 
				service.getLineState() == LineStates.Open && 
				(extension + 1) != this.extension) {
			dialing = true;
			service.dialConnection(extension + 1);
		}
	}

	public void onPhoneActionClick() {
		switch(service.getLineState()) {
			case Open:
				// do nothing
				dialing = false;
				break;
			case Busy:
				if (dialing) {
					service.terminateConnection();
					clearSound();
					dialing = false;
				}
				break;
			case Connecting:
				// do nothing
				break;
			case Dialing:
				if (dialing) {
					service.terminateConnection();
					clearSound();
				}
				break;
			case Ringing:
				if (dialing) {
					service.terminateConnection();
					dialing = false;
				} else {
					service.acceptConnection();
					dialing = false;
				}
				clearSound();
				break;
			case Talking:
				service.terminateConnection();
				dialing = false;
				break;
			case Terminating:
				dialing = false;
				break;
			case Error:
				if (dialing) {
					service.terminateConnection();
					dialing = false;
				}
				break;
		}
	}
	
	public void setSound(SoundTypes soundType) {
		if (sound != null) { 
			if (sound.getSoundType() == soundType)
				return;
			else
				clearSound();
		}
		sound = new SoundRunner(soundType);
		sound.start();
	}
	
	public void clearSound() {
		if (sound != null) {
			sound.interrupt();
			sound = null;
		}
	}
	
	public boolean validExtension(int extension) {
		return (extension < 16 && extension > -1);
	}
}
